/*
 * Copyright (c) 2003-2010, Live Media Pty. Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *     conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *  3. Neither the name of Live Media nor the names of its contributors may be used to endorse
 *     or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.argot.mcg;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.argot.ReferenceTypeMap;
import com.argot.ResourceDictionaryLoader;
import com.argot.TypeException;
import com.argot.TypeLibrary;
import com.argot.TypeLibraryLoader;
import com.argot.TypeMapperCore;
import com.argot.TypeMapperDynamic;
import com.argot.TypeMapperError;
import com.argot.auto.TypeSimpleReader;
import com.argot.auto.TypeSimpleWriter;
import com.argot.common.CommonLoader;
import com.argot.dictionary.DictionaryLoader;
import com.argot.meta.MetaExtensionLoader;
import com.argot.meta.MetaLoader;
import com.argot.remote.MetaObject;
import com.argot.remote.RemoteLoader;
import com.colony.container.simple.SimpleLoader;
import com.colony.container.simple.SimpleLocation;
import com.colony.remote.rpc.RpcLoader;


public class ArgotMicroCodeGenerator 
{
	public static final String VERSION = "1.0.0";

	private static TypeLibraryLoader libraryLoaders[] = {
		new MetaLoader(),
		new DictionaryLoader(),
		new MetaExtensionLoader(),
		new CommonLoader(),
		new RemoteLoader(),
	};	

	public static void argotCompile( File sourceDictionary, File headerFile, File sourceFile, String baseType, String baseVersion ) 
	throws FileNotFoundException, TypeException, IOException
	{
		System.out.println("Argot MCG (Micro Code Generator) Version "+ VERSION );
		System.out.println("Copyright 2004-2010 (C) Live Media Pty Ltd.");
		System.out.println("www.einet.com.au\n");

		TypeLibrary library = new TypeLibrary(libraryLoaders);

		//library.loadLibrary(new ResourceDictionaryLoader("test/data/netargot.dictionary"));
		
		// TODO This hard codes the simple RPC protocol and Simple container.
		library.loadLibrary( new RpcLoader() );
		library.loadLibrary( new SimpleLoader() );
		
		// Load the specified dictionary.
		library.loadLibrary(new ResourceDictionaryLoader(sourceDictionary.getAbsolutePath()));

		int simpleId = library.getTypeId(SimpleLocation.TYPENAME,"1.3");
		if ( library.getTypeState( simpleId ) == TypeLibrary.TYPE_REGISTERED )
		{
			library.bind( simpleId,
				new TypeSimpleReader(new SimpleLocation.SimpleLocationReader()),
				new TypeSimpleWriter(new SimpleLocation.SimpleLocationWriter()),
				SimpleLocation.class );
		}
		
		ReferenceTypeMap map = new ReferenceTypeMap( library, new TypeMapperCore(new TypeMapperDynamic(new TypeMapperError())));
		map.setReferenceMap(map);
		
		MetaObject base = new MetaObject( new SimpleLocation(0), map.getLibrary().getTypeId(baseType));
		
		int interfaceId = library.getDefinitionId( baseType,baseVersion);
		ArgotSourceGenerator amg = new ArgotSourceGenerator( library, map, base, interfaceId );
		FileOutputStream file = new FileOutputStream( sourceFile );
		amg.generateOutput( file );
		file.close();
		
		FileOutputStream header = new FileOutputStream( headerFile );
		ArgotHeaderGenerator ahg = new ArgotHeaderGenerator(library, map);
		ahg.generateOutput( header );
		header.close();
	}

	public static void main(String[] args)
	{
		try 
		{
			if ( args.length == 0 )
			{
				System.out.println("Usage: amcg <input.dictionary> <type name>");
				System.exit(-1);
			}

			File dictionaryFile = new File("data/nettest.dictionary");
			File headerFile = new File("dictionary.h");
			File sourceFile = new File("dictionary.c");
			String baseType = "test";
			String baseVersion = "1.3";

			argotCompile( dictionaryFile, headerFile, sourceFile, baseType, baseVersion );
		} 
		catch (FileNotFoundException e) 
		{
			e.printStackTrace();
		} 
		catch (TypeException e) 
		{
			e.printStackTrace();
		}
		catch (IOException e )
		{
			e.printStackTrace();
		}
		catch (Exception e)
        {
            e.printStackTrace();
        }
	}
	

}
